﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Xml.Linq;
using GameEngine.Model.Data;
using PureMVC.Patterns;
using GameEngine.Libs;

namespace GameEngine.Model
{
    /// <summary>
    /// </summary>
    public class WorldDataProxy<ItemVOId> : DataProxy, IWorldDataProxy<ItemVOId>
        where ItemVOId : IComparable<ItemVOId>
    {
        IMapDataProxy<ItemVOId> map;
        public IMapDataProxy<ItemVOId> Map { 
            get {
                if (map == null)
                    map = IMapDataProxyConstants<ItemVOId>.GetMapDataProxy(VO.Map.Name);
                return map;
            } 
        }
        public IDictionary<IThingVOId<ItemVOId>, IThingDataProxy<ItemVOId>> Items { get; set; }
        public IDictionary<Point, List<IThingVOId<ItemVOId>>> ItemsMapPosition { get; set; } 
        
        //IDictionary<long,IDictionary<Point, IThingDataProxy>> TileOcupation = new Dictionary<long,IDictionary<Point, IThingDataProxy>>();
        public bool Pause { get; set; }

        /*TileMapViewVO tileMapView;//map type, tile size, maxheight, height diff
        List<ItemViewVO> itemView;//ficheiro jpg, settings
        List<IThingTypeVO> things; //id item views,item types(forca, velocidade)
        public void LoadConfig() { }
        MapVO map; //map size, mapHeights
        List<IItemVO> items;//position, currenthealth
        //items
        public void LoadLevel() { }*/

        //public string TILESIZEUPDATED_NOTIFICATION
        //{
        //    get;
        //    protected set;
        //}
        //public string MAXHEIGHTUPDATED_NOTIFICATION
        //{
        //    get;
        //    protected set;
        //}
        //public string MINHEIGHTUPDATED_NOTIFICATION
        //{
        //    get;
        //    protected set;
        //}
        //public string TILEHEIGHTUNITUPDATED_NOTIFICATION
        //{
        //    get;
        //    protected set;
        //}

        /*public string ADDITEMTOMAP_NOTIFICATION
        {
            get;
            protected set;
        }
        public string REMOVEITEMFROMMAP_NOTIFICATION
        {
            get;
            protected set;
        }*/
        public string THINGADDED_NOTIFICATION { get; protected set; }
        public string THINGREMOVED_NOTIFICATION { get; protected set; }
        public string THINGMOVEWITHMOUSE_NOTIFICATION { get; protected set; }

        public IWorldVO<ItemVOId> VO
        {
            get { return Data as IWorldVO<ItemVOId>; }
        }

        public string WorldName {
            get { return VO.Name; }
            set { VO.Name = value; }
        }

        public IWorldVOId Id
        {
            get { return VO.Id; }
        }

        //public Point TileSize
        //{
        //    get { return VO.TileSize; }
        //    set
        //    {
        //        VO.TileSize = value;
        //        SendNotification(TILESIZEUPDATED_NOTIFICATION, this);
        //    }
        //}

        //public float MaxHeight
        //{
        //    get
        //    {
        //        return VO.MaxHeight;
        //    }
        //    set
        //    {
        //        VO.MaxHeight = value;
        //        SendNotification(MAXHEIGHTUPDATED_NOTIFICATION, this);
        //    }
        //}

        //public float MinHeight
        //{
        //    get
        //    {
        //        return VO.MinHeight;
        //    }
        //    set
        //    {
        //        VO.MinHeight = value;
        //        SendNotification(MINHEIGHTUPDATED_NOTIFICATION, this);
        //    }
        //}

        //public float TileHeightUnit
        //{
        //    get
        //    {
        //        return VO.TileHeightUnit;
        //    }
        //    set
        //    {
        //        VO.TileHeightUnit = value;
        //        SendNotification(TILEHEIGHTUNITUPDATED_NOTIFICATION, this);
        //    }
        //}

        public WorldDataProxy(IWorldVO<ItemVOId> world)
            : base(IWorldDataProxyConstants<ItemVOId>.CreateDataProxyName(world), world)
        {
            //TILESIZEUPDATED_NOTIFICATION = "tileSizeUpdated_" + ProxyName;
            //MAXHEIGHTUPDATED_NOTIFICATION = "maxHeightUpdated_" + ProxyName;
            //MINHEIGHTUPDATED_NOTIFICATION = "minHeightUpdated_" + ProxyName;
            //TILEHEIGHTUNITUPDATED_NOTIFICATION = "tileHeightUnitUpdated_" + ProxyName;
            //ADDITEMTOMAP_NOTIFICATION = "MapAddItem_"+name;
            //REMOVEITEMFROMMAP_NOTIFICATION = "MapRemoveItem_"+name;
            THINGADDED_NOTIFICATION = "ThingAdded_" + ProxyName;
            THINGREMOVED_NOTIFICATION = "ThingRemoved_" + ProxyName;
            THINGMOVEWITHMOUSE_NOTIFICATION = "ThingMoveWithMouse_" + ProxyName;

            Pause = false;
            Items = new Dictionary<IThingVOId<ItemVOId>,IThingDataProxy<ItemVOId>>();
            ItemsMapPosition = new Dictionary<Point, List<IThingVOId<ItemVOId>>>();
        }

        //public void LoadFromXML(XDocument doc)
        //{
        //    /*TODO List<List<ITileVO>> tiles = new List<List<ITileVO>>();
        //    foreach (XElement row in doc.Elements("tiles").Nodes())
        //    {
        //        List<ITileVO> tileRow = new List<ITileVO>();
        //        foreach (XElement tile in row.Nodes())
        //        {
        //            ITileVO tileVO = new MyTileVO();
        //            tileVO.Height = float.Parse(tile.Attribute("height").Value);
        //            foreach (XElement node in tile.Nodes())
        //                switch (node.Name.ToString())
        //                {
        //                    case "position":
        //                        tileVO.Position = new Point(
        //                            int.Parse(node.Attribute("x").Value),
        //                            int.Parse(node.Attribute("y").Value));
        //                        break;
        //                }
        //            tileRow.Add(tileVO);
        //        }
        //        tiles.Add(tileRow);
        //    }
        //    Map.Tiles = tiles;
        //    SendNotification(TILESUPDATED_NOTIFICATION, this);*/
        //}

        //public XDocument SaveToXML()
        //{
        //    return null;
        //    /*TODO
        //    XDocument doc = new XDocument();
        //    XElement mapNode = new XElement("map");
        //    XElement maxHeight = new XElement("maxHeight") { Value = Map.MaxHeight.ToString() };
        //    mapNode.Add(maxHeight);
        //    XElement size = new XElement("size");
        //    size.SetAttributeValue("x", Map.Size.X);
        //    size.SetAttributeValue("y", Map.Size.Y);
        //    mapNode.Add(size);
        //    XElement tileSize = new XElement("tileSize");
        //    tileSize.SetAttributeValue("x", Map.TileSize.X);
        //    tileSize.SetAttributeValue("y", Map.TileSize.Y);
        //    mapNode.Add(tileSize);
        //    //todo Camera
        //    XElement tilesNode = new XElement("tiles");
        //    foreach (List<ITileVO> tiles in Map.Tiles)
        //    {
        //        XElement rowNode = new XElement("row");
        //        foreach (ITileVO tile in tiles)
        //        {
        //            XElement tileNode = new XElement("tile");
        //            tileNode.SetAttributeValue("height", tile.Height.ToString());
        //            XElement position = new XElement("position");
        //            position.SetAttributeValue("x", tile.Position.X);
        //            position.SetAttributeValue("y", tile.Position.Y);
        //            tileNode.Add(position);
        //            rowNode.Add(tileNode);
        //        }
        //        tilesNode.Add(rowNode);
        //    }
        //    mapNode.Add(tilesNode);
        //    doc.Add(mapNode);
        //    return doc;*/
        //}

        public void Tick()
        {
            //throw new NotImplementedException();
        }

        public void RemoveItem(IThingDataProxy<ItemVOId> item) 
        {
            ItemsMapPosition[item.Position].Remove(item.Id);            
            Items.Remove(item.Id);
            VO.Items.Remove(item.VO);
            SendNotification(THINGREMOVED_NOTIFICATION, item);
        }

        public void RemoveAllItems()
        {
            foreach(IThingDataProxy<ItemVOId> item in Items.Values)
                SendNotification(THINGREMOVED_NOTIFICATION, item);
            Items.Clear();
            VO.Items.Clear();
        }

        public void InitializeItem(IThingDataProxy<ItemVOId> item)
        {
            item.WorldId = Id;
            Items.Add(item.Id, item);
            item.MapPosition = new Point()
            {
                X = (int)item.Position.X,
                Y = (int)item.Position.Y
            };
            if (!ItemsMapPosition.ContainsKey(item.MapPosition))
            {
                ItemsMapPosition.Add(item.MapPosition, new List<IThingVOId<ItemVOId>>());
            }
            ItemsMapPosition[item.MapPosition].Add(item.Id);
            Map.VO.Tiles[(int)item.MapPosition.X][(int)item.MapPosition.Y].Occupied = true;
            SendNotification(THINGADDED_NOTIFICATION, item);
        }

        public void AddItem(IThingDataProxy<ItemVOId> item)
        {
            InitializeItem(item);

            VO.Items.Add(item.VO);
        }

        public void ControlThingPosition(IThingDataProxy<ItemVOId> item) {
            SendNotification(THINGMOVEWITHMOUSE_NOTIFICATION, item);
        }

        //public override string Serialize()
        //{
        //    return Serializer.Serialize(this);
        //}
    }
}
